package qc.module.cms.api.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import qc.common.core.exception.QCPromptException;
import qc.module.cms.dto.article.ArticleQueryConditionDto;
import qc.module.cms.dto.article.ArticleQueryResultDto;
import qc.module.cms.dto.category.CategoryDto;
import qc.module.cms.dto.category.CategoryQueryConditionDto;
import qc.module.cms.dto.category.CategorySimpleDto;
import qc.module.cms.dto.display.DisplayCategoryArticlesDto;
import qc.module.cms.dto.display.DisplayCategoryInfoDto;
import qc.module.cms.dto.display.DisplayCommonInfoDto;
import qc.module.cms.dto.swipper.SwipperDto;
import qc.module.cms.dto.swipper.SwipperQueryConditionDto;
import qc.module.cms.service.CategoryService;
import qc.module.cms.service.DisplayService;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * DisplayController
 *
 * @author QuCheng Tech
 * @create 2023/5/26
 */
@RestController
@RequestMapping("/display")
public class DisplayController {
    @Autowired
    private RestTemplate restTemplate;

    private DisplayService displayService;

    private CategoryService categoryService;

    @Autowired
    public void setDisplayService(DisplayService displayService) {
        this.displayService = displayService;
    }

    @Autowired
    public void setCategoryService(CategoryService categoryService) {
        this.categoryService = categoryService;
    }

    /**
     * 获取CMS公用显示信息，包含栏目和二级栏目信息、链接分类和链接信息
     *
     * @return qc.module.cms.dto.display.DisplayCommonInfoDto
     * @author QuCheng Tech
     * @since 2023/5/29
     */
    @RequestMapping(value = "/common", method = {RequestMethod.GET})
    public DisplayCommonInfoDto getCommon() throws QCPromptException {
        return displayService.getCmsCommonInfo();
    }

    /**
     * 获取指定栏目Id的信息，包括当前栏目信息、文章和下一级栏目和文章
     *
     * @param id 栏目ID
     * @return qc.module.cms.dto.display.DisplayCategoryInfoDto
     * @author QuCheng Tech
     * @since 2023/5/29
     */
    @RequestMapping(value = "/category", method = {RequestMethod.GET})
    public DisplayCategoryInfoDto getCategoryByParam(@RequestParam int id) throws QCPromptException {
        return getCategoryDisplayInfo(id);
    }

    /**
     * 获取指定栏目Id的信息，包括当前栏目信息、文章和下一级栏目和文章
     *
     * @param id 栏目ID
     * @return qc.module.cms.dto.display.DisplayCategoryInfoDto
     * @author QuCheng Tech
     * @since 2023/5/29
     */
    @RequestMapping(value = "/category/{id}", method = {RequestMethod.GET})
    public DisplayCategoryInfoDto getCategoryByPath(@PathVariable int id) throws QCPromptException {
        return getCategoryDisplayInfo(id);
    }

    /**
     * 获取指定栏目Id的文章信息，包括当前栏目及当前栏目子级中的文章
     *
     * @param id 栏目ID
     * @return qc.module.cms.dto.display.DisplayCategoryArticlesDto
     * @author QuCheng Tech
     * @since 2024/1/22
     */
    @RequestMapping(value = "/categoryArticles", method = {RequestMethod.GET})
    public DisplayCategoryArticlesDto getCategoryArticlesByParam(@RequestParam int id) throws QCPromptException {
        return displayService.getCmsCategoryArticles(id);
    }

    /**
     * 获取指定栏目Id的文章信息，包括当前栏目及当前栏目子级中的文章
     *
     * @param id 栏目ID
     * @return qc.module.cms.dto.display.DisplayCategoryArticlesDto
     * @author QuCheng Tech
     * @since 2024/1/22
     */
    @RequestMapping(value = "/categoryArticles/{id}", method = {RequestMethod.GET})
    public DisplayCategoryArticlesDto getCategoryArticlesByPath(@PathVariable int id) throws QCPromptException {
        return displayService.getCmsCategoryArticles(id);
    }


    /***
     * 根据指定的栏目ID获取栏目的显示信息，包含当前栏目信息、文章和下一级栏目和文章信息
     *
     * @param categoryId 栏目ID
     * @return qc.module.cms.dto.display.DisplayCategoryInfoDto
     * @author QuCheng Tech
     * @since 2023/10/27
     */
    DisplayCategoryInfoDto getCategoryDisplayInfo(int categoryId) throws QCPromptException {
        //修改为id可以为0，为0时表示获取首页的信息，获取所有一级栏目信息显示
        //如果没有传入条件或者传入的栏目ID小于1，自动从栏目表中获取第1个栏目作为查询的栏目ID
        if (categoryId < 0x1) {
            CategoryQueryConditionDto categoryQueryConditionDto = new CategoryQueryConditionDto();
            categoryQueryConditionDto.setIsall(false);
            categoryQueryConditionDto.setIsdept(false);
            categoryQueryConditionDto.setIsvisible(false);
            List<CategorySimpleDto> categorySimpleDtos = categoryService.queryListSimple(categoryQueryConditionDto, null);
            if (categorySimpleDtos != null && categorySimpleDtos.size() > 0x0)
                categoryId = categorySimpleDtos.get(0x0).getId();
        }

        //获取当前栏目信息
        CategoryDto categoryDto = categoryService.get(categoryId, true);
        if (categoryDto == null)
            throw new QCPromptException("查询的栏目不存在");

        //调用service中的方法得到数据
        DisplayCategoryInfoDto result = displayService.getCmsCategoryAndArticleInfo(categoryDto);

        //特殊处理：针对栏目中的bodyStyle进行处理；如果配置的静态信息为空，根据配置的网址进行动态获取
        // 读取栏目中的版面布局配置信息
        JSONObject categoryLayoutJsonObject = null;
        if (!StringUtils.isBlank(categoryDto.getLayout())) {
            Object convertJsonObject = JSON.parse(categoryDto.getLayout());
            if (convertJsonObject instanceof JSONObject) {
                categoryLayoutJsonObject = (JSONObject) convertJsonObject;
                if (categoryLayoutJsonObject != null) {
                    //获取bodyStyle的配置
                    Object categoryBodyStyleObject = categoryLayoutJsonObject.get("bodyStyle");
                    if (categoryBodyStyleObject != null && categoryBodyStyleObject instanceof JSONObject) {
                        JSONObject categoryBodyStyleJsonObject = categoryLayoutJsonObject.getJSONObject("bodyStyle");
                        if (categoryBodyStyleJsonObject != null) {
                            //获取静态配置
                            Object staticBodyStyleJsonObject = categoryBodyStyleJsonObject.get("static");
                            if (staticBodyStyleJsonObject != null && staticBodyStyleJsonObject instanceof JSONArray) {
                                JSONArray staticBodyStyleJsonArray = categoryBodyStyleJsonObject.getJSONArray("static");
                                if (staticBodyStyleJsonArray != null && staticBodyStyleJsonArray.size() > 0x0) {
                                    //如果有静态配置，使用静态配置
                                    result.setBodyStyle(categoryBodyStyleJsonObject.getString("static"));
                                } else {
                                    //没有静态配置，判断是否有动态获取的地址，从动态获取地址中获取
                                    String url = categoryBodyStyleJsonObject.getString("dynamic");
                                    result.setBodyStyle(getWebSiteBodyStyle(url));
                                }
                            } else {
                                //没有静态配置，判断是否有动态获取的地址，从动态获取地址中获取
                                String url = categoryBodyStyleJsonObject.getString("dynamic");
                                result.setBodyStyle(getWebSiteBodyStyle(url));
                            }
                        }
                    }
                }
            }
        }

        return result;
    }

    /***
     * 根据指定的URL获取body中的style，返回json集合字符串
     *
     * @param url 用于获取style的url
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/10/27
     */
    String getWebSiteBodyStyle(String url) {
        if (!StringUtils.isBlank(url)) {
            //获取url必须要正确
            if (StringUtils.startsWith(url, "http://") || StringUtils.startsWith(url, "https://")) {
                try {
                    //设置超时时间，避免出现请求外部地址超时导致接口访问超时
                    ((HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory())
                            .setReadTimeout(3000);//连接超时时间3秒
                    ((HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory())
                            .setReadTimeout(3000);//读取超时时间3秒

                    //设置编码
                    restTemplate.getMessageConverters().set(0x1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

                    //url中有特殊字符，需要使用URI进行编码
                    URI uri = URI.create(url);
                    ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);

                    HttpStatus status = response.getStatusCode();

                    String responseBody = response.getBody();
                    //获取请求响应body的html文档对象
                    Document document = Jsoup.parse(responseBody);
                    if (document != null) {
                        Elements bodys = document.getElementsByTag("body");
                        if (bodys != null && bodys.size() > 0x0) {
                            Element body = bodys.get(0x0);
                            //从国家能源集团或云南公司网站获取body元素
                            Element element = body;

                            //测试获取class为cms-page的元素--渠成科技测试网站
                            //element = body.getElementsByClass("cms-page").get(0x0);

                            //获取元素的style
                            String bodyStyle = element.attr("style");
                            //测试节假日主题样式
                            //bodyStyle = "background-position: top center;background-repeat: no-repeat;padding-top:251px;background-image: url(/xhtml/chn/images/2022yd.png);";

                            Map<String, String> result = new HashMap<>();
                            //返回给前端的样式需要以JSON数组形式，手动对style进行解析
                            String[] styles = bodyStyle.split(";");
                            for (String s : styles) {
                                String[] keyValue = s.split(":");
                                String key = keyValue[0].trim(); // 样式名称
                                String value = keyValue[1].trim(); // 样式值
                                //System.out.println(key + ": " + value);
                                if (!StringUtils.isBlank(key) && !StringUtils.isBlank(value)) {
                                    //获取到style的值后，判断如果有图片url需要将url修改为完整路径
                                    if (StringUtils.equals(key, "background-image")) {
                                        value = value.replace("url(/", "url(" + url + "/");
                                    }

                                    if (result.containsKey(key))
                                        result.replace(key, value);
                                    else
                                        result.put(key, value);
                                }
                            }

                            //将style结果转换为JSON字符串
                            if (result != null && result.size() > 0x0)
                                return JSON.toJSONString(result);
                        }
                    }

                } catch (Exception ex) {
                    System.out.println("getWebSiteBodyStyle exception" + ex.getMessage());
                }
            }
        }

        return null;
    }

    /**
     * 获取CMS指定栏目轮播图信息，不包含横隔使用的轮播图信息；用于大屏中显示首页配置轮播图数据
     *
     * @return
     * @author QuCheng Tech
     * @since 2023/7/19
     */
    @RequestMapping(value = "/categoryswippers", method = {RequestMethod.POST, RequestMethod.GET})
    public List<SwipperDto> getCategorySwippersByParam(@RequestBody SwipperQueryConditionDto condition) throws QCPromptException {
        return displayService.getCategorySwippers(condition.getCid(), condition.getCount());
    }

    /**
     * 根据查询条件查询文章，查询条件中关键字必须指定，查询结果中的文章状态必须是已发布；
     *
     * @param condition: 查询条件
     * @return ArticleQueryResultDto 返回结果集
     * @author QcCheng Tech
     * @date 2023/7/21
     */
    @RequestMapping(value = "/queryarticles", method = {RequestMethod.POST, RequestMethod.GET})
    public ArticleQueryResultDto queryArticles(@RequestBody ArticleQueryConditionDto condition) throws QCPromptException {
        return displayService.queryArticles(condition);
    }

}
